import asyncio
import logging
from typing import List, Optional
from fastapi import FastAPI, HTTPException, BackgroundTasks, Query
from fastapi.responses import FileResponse, HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from edge_tts_service import EdgeTTSService
import uvicorn
import os
from datetime import datetime, timedelta

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

app = FastAPI(
    title="Edge TTS Web Service",
    description="基于 Microsoft Edge TTS 的语音合成服务",
    version="1.0.0"
)

# 添加 CORS 支持
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# 创建必要的目录
os.makedirs("static", exist_ok=True)
os.makedirs("web_output", exist_ok=True)

# 挂载静态文件目录
app.mount("/static", StaticFiles(directory="static"), name="static")

# 创建 TTS 服务实例
tts_service = EdgeTTSService(output_dir="web_output")

# 上次清理时间
last_cleanup_time = datetime.now()

class TTSRequest(BaseModel):
    text: str
    voice: Optional[str] = "zh-CN-XiaoxiaoNeural"

def check_and_cleanup():
    """检查并清理过期文件"""
    global last_cleanup_time
    
    # 每天只清理一次
    now = datetime.now()
    if (now - last_cleanup_time).days >= 1:
        logger.info("开始清理过期文件...")
        tts_service.clean_old_files(days_to_keep=7)  # 保留最近7天的文件
        last_cleanup_time = now
        logger.info("文件清理完成")

@app.get("/voices", response_model=List[dict])
async def list_voices(language: Optional[str] = Query("all", description="语言选择：all/zh/en")):
    """
    获取语音列表
    
    - language=all: 获取所有中英文声音
    - language=zh: 仅获取中文声音
    - language=en: 仅获取英文声音
    """
    try:
        if language == "zh":
            voices = await tts_service.get_chinese_voices()
        elif language == "en":
            voices = await tts_service.get_english_voices()
        else:  # all
            chinese_voices = await tts_service.get_chinese_voices()
            english_voices = await tts_service.get_english_voices()
            voices = chinese_voices + english_voices
        return voices
    except Exception as e:
        logger.error(f"获取声音列表失败: {str(e)}")
        raise HTTPException(status_code=500, detail=str(e))

@app.post("/api/synthesize")
@app.get("/api/synthesize")
async def synthesize_speech(
    background_tasks: BackgroundTasks,
    text: Optional[str] = Query(None),
    voice: Optional[str] = Query("zh-CN-XiaoxiaoNeural"),
    request: Optional[TTSRequest] = None
):
    """
    将文本转换为语音（支持 GET 和 POST 方法）
    
    GET 方法示例:
    - /api/synthesize?text=你好世界&voice=zh-CN-XiaoxiaoNeural
    - /api/synthesize?text=今天天气真好
    - /api/synthesize?text=Hello%20World&voice=zh-CN-YunxiNeural
    
    POST 方法示例:
    {
        "text": "你好世界",
        "voice": "zh-CN-XiaoxiaoNeural"
    }
    """
    start_time = datetime.now()
    try:
        # 处理 POST 请求
        if request:
            text = request.text
            voice = request.voice
        # 处理 GET 请求
        elif not text:
            raise HTTPException(status_code=400, detail="text 参数是必需的")
            
        logger.info(f"收到合成请求: text={text}, voice={voice}")
        
        # 更新服务使用的声音
        tts_service.voice = voice
        
        # 获取或生成语音文件
        file_path = await tts_service.text_to_speech(text)
        
        # 在后台检查并清理过期文件
        background_tasks.add_task(check_and_cleanup)
        
        # 计算处理时间
        end_time = datetime.now()
        process_time = (end_time - start_time).total_seconds() * 1000  # 转换为毫秒

        # 返回音频文件，添加处理时间到响应头
        response = FileResponse(
            file_path,
            media_type="audio/mpeg",
            filename=os.path.basename(file_path)
        )
        response.headers["X-Process-Time"] = f"{process_time:.2f}"
        return response
    except Exception as e:
        logger.error(f"语音合成失败: {str(e)}")
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/")
async def root():
    """返回带有 API 使用说明的 HTML 页面"""
    html_content = """
    <!DOCTYPE html>
    <html>
    <head>
        <title>晶莹果甜文本转语音服务使用说明</title>
        <style>
            body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
            .example { background: #f5f5f5; padding: 15px; border-radius: 5px; margin: 10px 0; }
            code { background: #e0e0e0; padding: 2px 5px; border-radius: 3px; }
        </style>
    </head>
    <body>
        <h1>晶莹果甜文本转语音服务使用说明</h1>
        
        <h2>1. Web 界面</h2>
        <p>访问 <a href="/static/index.html">/static/index.html</a> 使用 Web 界面</p>
        
        <h2>2. GET 方式调用示例</h2>
        <div class="example">
            <p>基本调用：</p>
            <code>/api/synthesize?text=你好世界</code>
            
            <p>指定声音：</p>
            <code>/api/synthesize?text=你好世界&voice=zh-CN-XiaoxiaoNeural</code>
            
            <p>包含空格的文本：</p>
            <code>/api/synthesize?text=今天%20天气%20真好</code>
            
            <p>完整示例：</p>
            <a href="/api/synthesize?text=你好世界&voice=zh-CN-XiaoxiaoNeural" target="_blank">点击测试</a>
        </div>
        
        <h2>3. POST 方式调用示例</h2>
        <div class="example">
            <pre>
POST /api/synthesize
Content-Type: application/json

{
    "text": "你好世界",
    "voice": "zh-CN-XiaoxiaoNeural"
}
            </pre>
        </div>
        
        <h2>4. 可用的声音</h2>
        <div class="example">
            <p>获取声音列表：</p>
            <ul>
                <li>所有声音：<code>GET /voices</code></li>
                <li>仅中文声音：<code>GET /voices?language=zh</code></li>
                <li>仅英文声音：<code>GET /voices?language=en</code></li>
            </ul>
            
            <p>常用中文声音：</p>
            <ul>
                <li>zh-CN-XiaoxiaoNeural (女声)</li>
                <li>zh-CN-YunxiNeural (男声)</li>
                <li>zh-CN-XiaoyiNeural (女声)</li>
                <li>zh-CN-YunyangNeural (男声)</li>
            </ul>
            
            <p>常用英文声音：</p>
            <ul>
                <li>en-US-AriaNeural (女声)</li>
                <li>en-US-GuyNeural (男声)</li>
                <li>en-GB-SoniaNeural (英式女声)</li>
                <li>en-GB-RyanNeural (英式男声)</li>
                <li>en-AU-NatashaNeural (澳式女声)</li>
                <li>en-CA-ClaraNeural (加拿大女声)</li>
            </ul>
        </div>
    </body>
    </html>
    """
    return HTMLResponse(content=html_content)

@app.get("/cleanup")
async def manual_cleanup():
    """手动触发清理过期文件"""
    try:
        tts_service.clean_old_files(days_to_keep=7)
        return {"message": "清理完成"}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

if __name__ == "__main__":
    # 启动服务
    uvicorn.run(
        "web_service:app",
        host="0.0.0.0",
        port=8000,
        reload=True
    ) 